//////////////////////////////////////////////////////////////////////////////////
//
// ActionScript 3.0 Common Library (MIT License)
// Copyright (c) 2009 AS3CommonCode | Tony Birleffi | http://www.mosaiceye.com
// 
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// The following people are credited with originating all or parts of this code:
// FlashDoctors | flashdoctors.sourceforge.net
//
//////////////////////////////////////////////////////////////////////////////////

package org.as3commoncode.net
{
	import org.as3commoncode.net.AbstractFile;
	import org.as3commoncode.net.IFile;
	import org.as3commoncode.net.QueryString;
	
	/**
	 * The URL class.
	 * 
	 * @see org.as3commoncode.net.AbstractFile;
	 * @see org.as3commoncode.net.IFile;
	 * 
	 * @author Tony Birleffi
	 */
	public class URL extends AbstractFile implements IFile
	{
		private var domain:String;
		private var protocol:String;
		private var port:Number = -1;
		private var path:String;
		private var filename:String;
		private var queryString:QueryString;
		
		/**
		 * Constructor.
		 * 
		 * @param href	String.
		 */
		public function URL(href:String)
		{
			this.queryString = new QueryString(null);
			
			//proto
			this.protocol = href.substring(0,href.indexOf("://"));
	
			var tmpUrl:String = href.substr(href.indexOf("://") + 3,href.length);
			var querySplit:Array = tmpUrl.split("?");
			var pathSplit:Array = String(querySplit[0]).split("/");
			var split0:String = pathSplit[0];
			//domain & port
			if(split0.indexOf(":") > -1)
			{
				this.domain = split0.substring(0,split0.indexOf(":"));
				this.port = parseInt(split0.substring(split0.indexOf(":")+1,split0.length));
			}
			else
			{
				this.domain = split0;
			}
			
			//path
			var tmpPath:String = "";
			if(pathSplit.length > 1)
			{
				for(var i:Number = 0;i<pathSplit.length;i++)
				{
					if(i>0)
					{
						if((i != pathSplit.length - 1) || (i == pathSplit.length - 1 && String(pathSplit[i]).indexOf(".") < 0))
						{
							tmpPath = tmpPath + "/" + pathSplit[i];
						}
					}
				}
			}
			this.path = tmpPath + "/";
			
			//file
			var tmpFile:String = pathSplit[pathSplit.length - 1];
			if(tmpFile.indexOf(".") > -1)
			{
				this.filename = tmpFile;
			}
			//queryString
			if(querySplit.length > 1)
			{
				this.queryString = new QueryString(querySplit[1]);
			}
		
		}
		
		/**
		 * Returns everything up to, but not including the filename. (Query string is also excluded).
		 * Given: http://www.example.com/test/one/two/file.aspx?test=1
		 * This would return: http://www.example.com/test/one/two.
		 * 
		 * @return String.
		 */
		public function getBaseURL():String
		{
			//trace("querystring " + this.queryString.toString() + " URL::getFullPath");
			var tmpUrl:String = this.protocol + "://" + this.domain;
			if(this.port > -1) tmpUrl = tmpUrl + ":" + this.port;
			tmpUrl = tmpUrl + this.path;
			return tmpUrl;
		}
		
		/**
		 * Returns the protocol, port, domain, path, filename, and query string - ie: the full URL.
		 * 
		 * @return String.
		 */
		override public function getFullPath():String
		{
			var tmpUrl:String = getBaseURL();
			if(this.filename != null) {
				tmpUrl += this.filename;
			}
			if(this.queryString != null)
			{
				tmpUrl = tmpUrl + this.queryString.toString();
			}
			
			return tmpUrl;
		}
		
		/**
		 * Get the domain.
		 * 
		 * @return String.
		 */
		public function getDomain():String
		{
			return this.domain;
		}
		
		/**
		 * Set the domain.
		 * 
		 * @param s		String.
		 */
		public function setDomain(s:String):void
		{
			this.domain = s;
		}
		
		/**
		 * Get the protocol.
		 * 
		 * @return String.
		 */
		public function getProtocol():String
		{
			return this.protocol;
		}
		
		/**
		 * Set the protocol.
		 * 
		 * @param s		String.
		 */
		public function setProtocol(s:String):void
		{
			var tmp:Array = s.split(":");
			this.protocol = tmp[0];
		}
		
		/**
		 * Get the port.
		 * 
		 * @return Number.
		 */
		public function getPort():Number
		{
			return this.port;
		}
		
		/**
		 * Set the port.
		 * 
		 * @param n		Number.
		 */
		public function setPort(n:Number):void
		{
			this.port = n;
		}
		
		/**
		 * Get the path.
		 * 
		 * @return String.
		 */
		override public function getPath():String
		{
			return this.path;
		}
		
		/**
		 * Set the path.
		 * 
		 * @param s		String.
		 */
		public function setPath(s:String):void
		{
			if(s.substr(0,1) != "/") s = "/" + s;
			if(s.substr(s.length-1,1) != "/") s = s + "/";
			this.protocol = s;
		}
		
		/**
		 * Get the filename.
		 * 
		 * @return String.
		 */
		override public function getFilename():String
		{
			return this.filename;
		}
		
		/**
		 * Set the filename.
		 * 
		 * @param s		String.
		 */
		public function setFilename(s:String):void
		{
			this.filename = s;
		}
		
		/**
		 * Get the querystring.
		 * 
		 * @return QueryString.
		 */
		public function getQueryString():QueryString
		{
			return this.queryString;
		}
		
		/**
		 * Set the querystring.
		 * 
		 * @param q		QueryString.
		 */
		public function setQueryString(q:QueryString):void
		{
			this.queryString = q;
		}
		
		/**
		 * Returns the URL as a string, is automatically called when this object is passed into trace.
		 * 
		 * @return String
		 */
		public function toString():String 
		{
			return getFullPath();
		}
	}
}
